package org.nerve.webmagic.downloader;

import org.nerve.webmagic.DriverBuilder;
import org.nerve.webmagic.bean.SpiderConfig;
import org.openqa.selenium.WebDriver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.Closeable;
import java.io.IOException;
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * org.nerve.webmagic.downloader
 * Created by zengxm on 2016/4/22 0022.
 */
public class DriverPool<T extends WebDriver> implements Closeable{
	private static Logger logger= LoggerFactory.getLogger(DriverPool.class);

	private static final int RUNNING=0;
	private static final int CLOSED=1;

	private final SpiderConfig config;
	private final int maxLen;
	private final DriverBuilder<T> driverBuilder;

	private AtomicInteger stat=new AtomicInteger(RUNNING);
	private AtomicInteger length=new AtomicInteger(0);

	private BlockingDeque<T> driverQ=new LinkedBlockingDeque<>();

	public DriverPool(SpiderConfig config, DriverBuilder<T> driverBuilder){
		this.config=config;
		this.maxLen=config.getThreadSize();
		this.driverBuilder=driverBuilder;
	}

	private void checkRunning(){
		if (!stat.compareAndSet(RUNNING, RUNNING)) {
			throw new IllegalStateException("Already closed!");
		}
	}

	public T getDriver() throws InterruptedException {
		checkRunning();
		T driver=driverQ.poll();
		logger.info("尝试获取WebDriver::::::::,threadName={}, drive={}",Thread.currentThread().getName(),driver);
		if(driver!=null){
			logger.info("成功获取WebDriver---------------，threadName={}",Thread.currentThread().getName());
			return driver;
		}else if(length.intValue()<=maxLen){
			synchronized (driverQ){
				try {
					T newDriver=driverBuilder.build(config);
					driverQ.add(newDriver);

					logger.info("成功创建Driver:{}, size={}",newDriver, driverQ.size());
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

		//线程阻塞，直到有driver的出现
		return driverQ.take();
	}

	public void returnToPool(T driver){
		checkRunning();
		logger.info("归还WebDriver---- {},drive={}",Thread.currentThread().getName(),driver);
		driverQ.add(driver);
	}

	@Override
	public void close() throws IOException {
		boolean b = stat.compareAndSet(RUNNING, CLOSED);
		if (!b) {
			throw new IllegalStateException("Already closed!");
		}
		logger.info("closing driver,size={}", driverQ.size());

		T d=null;
		while ((d=driverQ.poll())!=null){
			logger.info("Quit webDriver:{}" + d);
			d.quit();
			d.close();
			d = null;
		}
		logger.info("close all driver done! driverQ.size={}", driverQ.size());
	}
}
